#include <iostream>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include "../macro.h"

using std::cout;
using std::endl;

// 初始化共享内存
int *init_shm()
{
    int shmid = shmget(1000, sizeof(int), IPC_CREAT | 0600);
    ERR_CHECK(shmid, -1, "shmget")

    int *ret = (int *)shmat(shmid, NULL, 0);
    ERR_CHECK(*ret, -1, "shmat")

    return ret;
}

int init_sem()
{
    int semid = semget(1000, 2, IPC_CREAT | 0600);
    ERR_CHECK(semid, -1, "semget")

    unsigned short arr[2] = {5, 5};
    int ret = semctl(semid, 0, SETALL, arr);
    ERR_CHECK(ret, -1, "semctl")

    return semid;
}

struct sembuf p1{0, -1, SEM_UNDO}, v1{0, 1, SEM_UNDO};
struct sembuf p2{1, -1, SEM_UNDO}, v2{1, 1, SEM_UNDO};

void pro(int semid, int *num)
{
    int remain = semctl(semid, 0, GETVAL);
    ERR_CHECK(remain, -1, "semctl")

    // 当信号量的值为 0 时会阻塞，等待信号量不为 0 ，类似信号灯的红灯
    semop(semid, &p1, 1);
    printf("当前共保留%d件商品\n", ++(*num));
    semop(semid, &v2, 1);
}

void con(int semid, int *num)
{
    int remain = semctl(semid, 1, GETVAL);
    ERR_CHECK(remain, -1, "semctl")

    semop(semid, &p2, 1);
    printf("当前共保留%d件商品\n", --(*num));
    semop(semid, &v1, 1);
}

void start()
{
    int semid = init_sem();
    int *num = init_shm();
    *num = 5;
    if(fork()){
        while(1){
            pro(semid, num);
            sleep(2);
        }
        wait(NULL);
        printf("processor stop!\n");
    }else{
        while(1){
            con(semid, num);
            sleep(1);
        }
    }
}

int main(int args, char *argv[])
{
    start();
    return 0;
}